package com.aforce3.trailertracer.scenes;

import java.util.ArrayList;

import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import com.aforce3.trailertracer.Material;
import com.aforce3.trailertracer.Ray;
import com.aforce3.trailertracer.optimizations.BoundingBox;

public abstract class Primitive extends Scene
{
	Material material = new Material();
	ArrayList<PointLight> lights;
	
	public Material getMaterial()
	{
		return material;
	}

	public void setMaterial(Material m)
	{
		material = m;
	}

	public Color3f getColor(Ray ray)
	{
		return getColor(ray, null);
	}

	public Ray calculateReflection(Ray ray)
	{
		return calculateReflection(ray, new Point3d(0, 0, 0));
	}

	/** Calculates the reflected ray **/
	public Ray calculateReflection(Ray ray, Point3d intersect)
	{
		Vector3d normal = getNormal(ray);

		Vector3d reflectedRay = new Vector3d();
		Vector3d temp = new Vector3d();

		reflectedRay.add(ray.getDirection());
		temp.add(normal);
		float dotVal = (float) temp.dot(ray.getDirection());
		temp.scale(dotVal);

		temp.scale(2);
		reflectedRay.sub(temp);
		reflectedRay.normalize();

		Ray newRay = new Ray(new Point3d(intersect), reflectedRay, ray.depth + 1);
		return newRay;
	}

	public abstract Vector3d getNormal(Ray ray);

	public ArrayList<PointLight> getLights()
	{
		if(lights == null)
		{
			lights = new ArrayList<PointLight>();
			if(isLight())
			{
				lights.add((PointLight) this);
			}
			return lights;
		}
		return lights;
	}

	public Scene getClosest(Ray ray, Scene self)
	{
		if(getDistance(ray) > 0 && this != self)
		{
			return this;
		}
		return null;
	}

	public Scene getClosestObject(Ray ray, Scene self)
	{
		if(getDistance(ray) > 0 && this != self && !this.isLight())
		{
			return this;
		}
		return null;
	}

	public Color3f getRayColor(Ray ray)
	{
		// if (getRoot().getClosest(ray, this) != null && !getRoot().getClosest(ray, this).isLight()){
		// return getRoot().getColor(ray, this);
		// }
		// get closest object does not get Lights
		Scene closest = getRoot().getClosestObject(ray, this);
		if(closest != null)
		{
			return closest.getColor(ray, this);
		}
		return null;
	}
}
